﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using nl.tno.ict.multitouch.wpfmultitouch.events;
using System.ComponentModel;

namespace nl.tno.ict.multitouch.wpfmultitouch.controls
{
    /// <summary>
    /// Interaction logic for MTKeyboard.xaml
    /// </summary>
    public partial class MTKeyboard : UserControl, MTObject
    {
        private bool _isUpper = false;
        private bool _leftCtrlDown = false;
        private bool _selectText = false;
        private bool _buttonFocusFeedback = true;
        private bool _buttonAdornerFeedback = false;
        private int _timeout = 1000;
        private int _fingerCount;        

        #region MTObject Members

        public bool CanBeScaled { get { return MTProperties.GetCanBeScaled(this); } set { MTProperties.SetCanBeScaled(this, value); } }
        public bool CanBeDragged { get { return MTProperties.GetCanBeDragged(this); } set { MTProperties.SetCanBeDragged(this, value); } }
        public bool CanBeClicked { get { return MTProperties.GetCanBeClicked(this); } set { MTProperties.SetCanBeClicked(this, value); } }
        public bool CanBeRotated { get { return MTProperties.GetCanBeRotated(this); } set { MTProperties.SetCanBeRotated(this, value); } }
        /// <summary>
        /// Gets or sets a bool that describes the value of a AdornersEnabledProperty for the element.
        /// </summary>
        public bool AdornersEnabled { get { return MTProperties.GetAdornersEnabled(this); } set { MTProperties.SetAdornersEnabled(this, value); } }

    
        #endregion

        #region MTObject Members


        public bool IsDragging
        {
            get { return MTProperties.GetIsDragging(this); }
            set { MTProperties.SetIsDragging(this, value); }
        }

        public bool IsScaling
        {
            get{return MTProperties.GetIsScaling(this); }
            set { MTProperties.SetIsScaling(this, value);}
        }

        public bool IsRotating
        {
            get{ return MTProperties.GetIsRotating(this); }
            set {MTProperties.SetIsRotating(this, value); }
        }

        #endregion

        #region MTObject Members

        public event nl.tno.ict.multitouch.wpfmultitouch.events.NotMovedEventArgs NotMoved;

        #endregion

        /// <summary>
        /// Gets or sets the timeout, in ms, used to by the NotMoved event. Default: 1000 ms
        /// </summary>
        void MTObject.NotMoved()
        {
            if (NotMoved != null)
                NotMoved(this, new EventArgs());
        }

        #region MTObject Members

      

        int MTObject.Timeout
        {
            get { return _timeout; }
            set { _timeout = value; }
        }

        #endregion

        public event ControlKeyboardButtonHandler MTKeyboardButtonPressed;

        /// <summary>
        /// Gets the value of the shift key
        /// </summary>
        public bool IsUpperKey { get { return _isUpper; } }

        /// <summary>
        /// Gets or sets a bool that describes the value of a SelectTextProperty for the element.
        /// </summary>
        public bool SelectText { get { return _selectText; } set { _selectText = value; } }

        /// <summary>
        /// Gets or sets a bool that describes the value of a ButtonFocusFeedbackProperty for the element.
        /// </summary>
        public bool ButtonFocusFeedback { get { return _buttonFocusFeedback; } set { _buttonFocusFeedback = value; } }

        /// <summary>
        /// Gets or sets a bool that describes the value of a ButtonAdornerFeedbackProperty for the element.
        /// </summary>
        public bool ButtonAdornerFeedback { get { return _buttonAdornerFeedback; } set { _buttonAdornerFeedback = value; } }

        /// <summary>
        /// Constructor of MTKeyboard
        /// </summary>
        public MTKeyboard()
        {
            InitializeComponent();
            // Sets the TouchEnabledObjectProperty for the element always true.
            MTProperties.SetTouchEnabled(this, true);
            
            this.CanBeClicked = true;
            this.CanBeDragged = true;
            this.CanBeRotated = true;
            this.CanBeScaled = true;
            this.AdornersEnabled = false;

            this.Loaded += new RoutedEventHandler(MTKeyboard_Loaded);
        }

        /// <summary>
        /// When the MTKeyboard is loaded the property ButtonAdornerFeedback will be checked 
        /// whether to set the AdornerEnabled property for the buttons.
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">RoutedEventArgs</param>
        private void MTKeyboard_Loaded(object sender, RoutedEventArgs e)
        {
            if (_buttonAdornerFeedback)
            {
                foreach (object key in this.KeyboardCanvas.Children)
                {
                    if (key is MTButton)
                        ((MTButton)key).AdornersEnabled = true;
                }
            }
        }

        /// <summary>
        /// Detects if the key is up
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">KeyEventArgs</param>
        private void MTButton_KeyUp(object sender, KeyEventArgs e)
        {
            if (_buttonFocusFeedback)
            {
                ((MTButton)sender).Background = Brushes.Red;
                ((MTButton)sender).Width -= 6;
                ((MTButton)sender).Height -= 6;
                MTCanvas.SetLeft(((MTButton)sender), MTCanvas.GetLeft((MTButton)sender) + 3);
                MTCanvas.SetTop(((MTButton)sender), MTCanvas.GetTop((MTButton)sender) + 3);
            }

            Key pressedKey = (Key)new EnumConverter(typeof(Key)).ConvertFromString(((MTButton)e.Source).Tag.ToString());


            if (pressedKey == Key.LeftShift || pressedKey == Key.RightShift)
            {
                if (_isUpper) { this._isUpper = false; }
                else {this._isUpper = true; }
                this.setKeyContent();
            }
            else if (pressedKey == Key.LeftCtrl) { _leftCtrlDown = false; }
                else if (pressedKey == Key.Escape) {
                    ((MTCanvas)this.Parent).Children.Remove(this);
                    //this.Visibility = Visibility.Collapsed;
                    
                }
        
            
        }

        /// <summary>
        /// Detects if the key is down
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">KeyEventArgs</param>
        private void MTButton_KeyDown(object sender, KeyEventArgs e)
        {
            if (_buttonFocusFeedback)
            {
                ((MTButton)sender).Background = Brushes.Red;
                ((MTButton)sender).Width += 6;
                ((MTButton)sender).Height += 6;
                MTCanvas.SetLeft(((MTButton)sender), MTCanvas.GetLeft((MTButton)sender) - 3);
                MTCanvas.SetTop(((MTButton)sender), MTCanvas.GetTop((MTButton)sender) - 3);
            }

            if ((Key)(new EnumConverter(typeof(Key)).ConvertFromString(((MTButton)e.Source).Tag.ToString())) == Key.LeftShift || 
                (Key)(new EnumConverter(typeof(Key)).ConvertFromString(((MTButton)e.Source).Tag.ToString())) == Key.RightShift || 
                (Key)(new EnumConverter(typeof(Key)).ConvertFromString(((MTButton)e.Source).Tag.ToString())) == Key.CapsLock)
            {
                if (_isUpper)
                    this._isUpper = false;
                else
                    this._isUpper = true;
                this.setKeyContent();
            }
            else if ((Key)(new EnumConverter(typeof(Key)).ConvertFromString(((MTButton)e.Source).Tag.ToString())) == Key.LeftCtrl)
                _leftCtrlDown = true;
        }

        /// <summary>
        /// Sets the key contant to lower or to upper case
        /// </summary>
        private void setKeyContent()
        {
            foreach (object key in this.KeyboardCanvas.Children)
            {
                if (key is MTButton && this.keyInAlfabet((Key)(new EnumConverter(typeof(Key)).ConvertFromString(((MTButton)key).Tag.ToString()))))
                    if (_isUpper)
                        ((MTButton)key).Content = ((MTButton)key).Content.ToString().ToUpper();
                    else
                        ((MTButton)key).Content = ((MTButton)key).Content.ToString().ToLower();
            }
        }

        /// <summary>
        /// Checks if the Key is an alfabet character.
        /// </summary>
        /// <param name="key">Key to check</param>
        /// <returns></returns>
        private bool keyInAlfabet(Key key)
        {
            if (key == Key.A || key == Key.B || key == Key.C || key == Key.D ||
                key == Key.E || key == Key.F || key == Key.G || key == Key.H ||
                key == Key.I || key == Key.J || key == Key.K || key == Key.L ||
                key == Key.M || key == Key.N || key == Key.O || key == Key.P ||
                key == Key.Q || key == Key.R || key == Key.S || key == Key.T ||
                key == Key.U || key == Key.V || key == Key.W || key == Key.X ||
                key == Key.Y || key == Key.Z)
                return true;
            return false;
        }

        /// <summary>
        /// Throws an event with the value of the current pressed key
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void mtButton_Click(object sender, RoutedEventArgs e)
        {
            if ((Key)(new EnumConverter(typeof(Key)).ConvertFromString(((MTButton)e.Source).Tag.ToString())) == Key.A && _leftCtrlDown)
                _selectText = true;
            try
            {                
                if (MTKeyboardButtonPressed != null) MTKeyboardButtonPressed(this, new ControlKeyboardEventArgs((Key)(new EnumConverter(typeof(Key)).ConvertFromString(((MTButton)e.Source).Tag.ToString()))));
            }
            catch(Exception ex)
            {
                Console.WriteLine("Error: Keyboard not set to an texteditor : " + ex.ToString());
            }
        }

        public int FingerCount
        {
            get
            {
                return _fingerCount;
            }
            set
            {
                _fingerCount = value;
            }
        }

        /// <summary>
        /// Gets or sets the onTop dependency property. When true, when a finger touches the object the object
        /// gets on top of the screen (z-index changes).
        /// </summary>
        public bool OnTop
        {
            get { return MTProperties.GetOnTop(this); }
            set { MTProperties.SetOnTop(this, value); }
        }

        /// <summary>
        /// Set the object TouchEnabled. When an object isn't touchEnabled interaction with fingers is not
        /// possible (nothing will happen).
        /// </summary>
        public bool TouchEnabled
        {
            get { return MTProperties.GetTouchEnabled(this); }
            set { MTProperties.SetTouchEnabled(this, value); }
        }

        #region IComponentConnector Members


        void System.Windows.Markup.IComponentConnector.InitializeComponent()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
